package router

import (
	"go.uber.org/zap"
	"live-core/core"
	"live-core/logging"
	"time"

	webrtc "github.com/geekerstar/libv/format/webrtcv3"
	"github.com/gin-gonic/gin"
)

func StreamWebRTC(c *gin.Context) {
	if !core.StreamManager.ChannelExist(c.Param("uuid"), c.Param("channel")) {
		c.IndentedJSON(500, Message{Status: 0, Payload: core.ErrorStreamNotFound.Error()})
		logging.ZapLog.Error(core.ErrorStreamNotFound.Error(),
			zap.String("stream", c.Param("uuid")), zap.String("channel", c.Param("channel")),
			zap.String("call", "ChannelExist"))
		return
	}
	core.StreamManager.ChannelRun(c.Param("uuid"), c.Param("channel"))
	codecs, err := core.StreamManager.ChannelCodecs(c.Param("uuid"), c.Param("channel"))
	if err != nil {
		c.IndentedJSON(500, Message{Status: 0, Payload: err.Error()})
		logging.ZapLog.Error(err.Error(),
			zap.String("stream", c.Param("uuid")), zap.String("channel", c.Param("channel")),
			zap.String("call", "StreamCodecs"))

		return
	}
	muxerWebRTC := webrtc.NewMuxer(webrtc.Options{PortMin: core.StreamManager.ServerWebRTCPortMin(), PortMax: core.StreamManager.ServerWebRTCPortMax()})
	answer, err := muxerWebRTC.WriteHeader(codecs, c.PostForm("data"))
	if err != nil {
		c.IndentedJSON(400, Message{Status: 0, Payload: err.Error()})
		logging.ZapLog.Error(err.Error(),
			zap.String("stream", c.Param("uuid")), zap.String("channel", c.Param("channel")),
			zap.String("call", "WriteHeader"))

		return
	}
	_, err = c.Writer.Write([]byte(answer))
	if err != nil {
		c.IndentedJSON(400, Message{Status: 0, Payload: err.Error()})
		logging.ZapLog.Error(err.Error(),
			zap.String("stream", c.Param("uuid")), zap.String("channel", c.Param("channel")),
			zap.String("call", "Write"))

		return
	}
	go func() {
		cid, ch, _, err := core.StreamManager.ClientAdd(c.Param("uuid"), c.Param("channel"), core.WEBRTC)
		if err != nil {
			c.IndentedJSON(400, Message{Status: 0, Payload: err.Error()})
			logging.ZapLog.Error(err.Error(),
				zap.String("stream", c.Param("uuid")), zap.String("channel", c.Param("channel")),
				zap.String("call", "ClientAdd"))

			return
		}
		defer core.StreamManager.ClientDelete(c.Param("uuid"), cid, c.Param("channel"))
		var videoStart bool
		noVideo := time.NewTimer(10 * time.Second)
		for {
			select {
			case <-noVideo.C:
				c.IndentedJSON(500, Message{Status: 0, Payload: core.ErrorStreamNoVideo.Error()})
				logging.ZapLog.Error(core.ErrorStreamNoVideo.Error(),
					zap.String("stream", c.Param("uuid")), zap.String("channel", c.Param("channel")),
					zap.String("call", "ErrorStreamNoVideo"))

				return
			case pck := <-ch:
				if pck.IsKeyFrame {
					noVideo.Reset(10 * time.Second)
					videoStart = true
				}
				if !videoStart {
					continue
				}
				err = muxerWebRTC.WritePacket(*pck)
				if err != nil {
					logging.ZapLog.Error(err.Error(),
						zap.String("stream", c.Param("uuid")), zap.String("channel", c.Param("channel")),
						zap.String("call", "WritePacket"))
					return
				}
			}
		}
	}()
}
